﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace InSTEDD.Labs.Geo.Formatting
{
	internal class UserGeoInputFormatter
    {
        const string Separator = "*";

		List<UserGeoInputFormatter> chainOfFormatters;

        public UserGeoInputFormatter()
            : this(true)
        { }

		protected UserGeoInputFormatter(bool buildChain)
        {
            if (buildChain)
            {
				chainOfFormatters = new List<UserGeoInputFormatter>();
                chainOfFormatters.Add(new ForgettingLastAsteriskFormatter());
                chainOfFormatters.Add(new LatLongUsingUsingPointsFormatter());
                chainOfFormatters.Add(new SpacesAroundAsterisksFormatter());
            } 
        }

        public virtual string Format(string message)
        {
            string result = message;

            this.chainOfFormatters.ForEach(
				delegate(UserGeoInputFormatter formatter)
                {
                    result = formatter.Format(result);
                }
            );

            return result;
        }

        public string[] SplitMessage(string message)
        {
            return message.Split(Separator.ToCharArray());
        }

        protected string JoinMessage(params string[] messageParts)
        {
            return string.Join(Separator, messageParts);
        }

		class SpacesAroundAsterisksFormatter : UserGeoInputFormatter
        {
            public SpacesAroundAsterisksFormatter()
                : base(false)
            { }

            public override string Format(string message)
            {
                string[] messageParts = SplitMessage(message);
                if (messageParts.Length == 3)
                {
                    return JoinMessage(messageParts[0].Trim(), messageParts[1].Trim(), messageParts[2].Trim());
                }

                return message;
            }
        }

		class LatLongUsingUsingPointsFormatter : UserGeoInputFormatter
        {
            public LatLongUsingUsingPointsFormatter()
                : base(false)
            { }

            public override string Format(string message)
            {
                string[] messageParts = SplitMessage(message);
                if (messageParts.Length == 3)
                {
                    return JoinMessage(messageParts[0].Replace(",", "."), messageParts[1].Replace(",", "."), messageParts[2]);
                }

                return message;
            }
        }

		class ForgettingLastAsteriskFormatter : UserGeoInputFormatter
        {
            public ForgettingLastAsteriskFormatter()
                : base(false)
            { }

            public override string Format(string message)
            {
                string[] messageParts = SplitMessage(message);
                if (messageParts.Length == 2 && messageParts[1].Length > 0)
                {
                    char lastCharacter = messageParts[1][0];
                    StringBuilder longitude = new StringBuilder();
                    foreach (char character in messageParts[1])
                    {
                        if (Char.IsDigit(lastCharacter) && (Char.IsWhiteSpace(character) || Char.IsLetter(character)))
                        {
                            break;
                        }

                        longitude.Append(character);
                        lastCharacter = character;
                    }

                    if (!longitude.ToString().Equals(messageParts[1]))
                    {
                        return JoinMessage(messageParts[0], longitude.ToString(), messageParts[1].Replace(longitude.ToString(), string.Empty));
                    }
                }

                return message;
            }
        }
    }
}
